/**
 * @file benchmark_logger.cpp
 * @brief 日志模块性能基准测试
 * @author Enterprise Logger Team
 * @date 2024
 */

#include "LoggerManager.h"
#include <chrono>
#include <thread>
#include <vector>
#include <atomic>
#include <iostream>
#include <iomanip>
#include <cstring>

using namespace logger;
using namespace std::chrono;

class Benchmark
{
public:
    struct Result
    {
        std::string name;
        int         numThreads;
        int         numLogs;
        double      totalTimeMs;
        double      throughput;
        double      avgLatencyUs;
    };

    static void runAllBenchmarks()
    {
        std::cout << "=== Enterprise Logger Performance Benchmark ===" << std::endl;
        std::cout << std::endl;

        // 初始化日志系统
        LogConfig config;
        config.moduleName    = "benchmark";
        config.logDirectory  = "./benchmark_logs";
        config.maxFileSize   = 500 * 1024 * 1024;   // 500MB
        config.flushInterval = 3;
        config.minLevel      = logger::LogLevel::INFO_LEVEL;
        config.asyncMode     = true;
        config.consoleOutput = false;   // 关闭控制台输出以获得更准确的性能数据

        if (!InitLogger(config)) {
            std::cerr << "Failed to initialize logger!" << std::endl;
            return;
        }

        std::vector<Result> results;

        // 单线程基准测试
        results.push_back(singleThreadBenchmark(100000));
        results.push_back(singleThreadBenchmark(1000000));

        // 多线程基准测试
        results.push_back(multiThreadBenchmark(4, 25000));
        results.push_back(multiThreadBenchmark(8, 12500));
        results.push_back(multiThreadBenchmark(16, 6250));
        results.push_back(multiThreadBenchmark(32, 3125));

        // 极限压力测试
        results.push_back(stressBenchmark());

        // 不同消息长度测试
        results.push_back(messageLengthBenchmark(100));
        results.push_back(messageLengthBenchmark(500));
        results.push_back(messageLengthBenchmark(1000));

        // 打印结果
        printResults(results);

        // 关闭日志系统
        ShutdownLogger();
    }

private:
    static Result singleThreadBenchmark(int numLogs)
    {
        Result result;
        result.name       = "Single Thread";
        result.numThreads = 1;
        result.numLogs    = numLogs;

        std::cout << "Running single thread benchmark (" << numLogs << " logs)..." << std::endl;

        auto start = high_resolution_clock::now();

        for (int i = 0; i < numLogs; ++i) {
            LOG_INFO << "Benchmark log #" << i << " timestamp: "
                     << duration_cast<microseconds>(high_resolution_clock::now().time_since_epoch())
                            .count();
        }

        auto end      = high_resolution_clock::now();
        auto duration = duration_cast<milliseconds>(end - start);

        result.totalTimeMs  = duration.count();
        result.throughput   = (numLogs * 1000.0) / result.totalTimeMs;
        result.avgLatencyUs = (result.totalTimeMs * 1000.0) / numLogs;

        std::cout << "  Completed in " << result.totalTimeMs << "ms" << std::endl;

        // 等待异步写入完成
        std::this_thread::sleep_for(std::chrono::seconds(1));

        return result;
    }

    static Result multiThreadBenchmark(int numThreads, int logsPerThread)
    {
        Result result;
        result.name       = "Multi Thread";
        result.numThreads = numThreads;
        result.numLogs    = numThreads * logsPerThread;

        std::cout << "Running multi-thread benchmark (" << numThreads << " threads, "
                  << logsPerThread << " logs/thread)..." << std::endl;

        std::atomic<int>         totalLogged(0);
        std::vector<std::thread> threads;

        auto threadFunc = [&totalLogged, logsPerThread](int threadId) {
            for (int i = 0; i < logsPerThread; ++i) {
                LOG_INFO << "Thread-" << threadId << " Log-" << i << " Total-"
                         << totalLogged.fetch_add(1);
            }
        };

        auto start = high_resolution_clock::now();

        for (int i = 0; i < numThreads; ++i) {
            threads.emplace_back(threadFunc, i);
        }

        for (auto& t : threads) {
            t.join();
        }

        auto end      = high_resolution_clock::now();
        auto duration = duration_cast<milliseconds>(end - start);

        result.totalTimeMs  = duration.count();
        result.throughput   = (result.numLogs * 1000.0) / result.totalTimeMs;
        result.avgLatencyUs = (result.totalTimeMs * 1000.0) / result.numLogs;

        std::cout << "  Completed in " << result.totalTimeMs << "ms" << std::endl;

        // 等待异步写入完成
        std::this_thread::sleep_for(std::chrono::seconds(1));

        return result;
    }

    static Result stressBenchmark()
    {
        Result result;
        result.name       = "Stress Test";
        result.numThreads = 50;
        int logsPerThread = 2000;
        result.numLogs    = result.numThreads * logsPerThread;

        std::cout << "Running stress test (" << result.numThreads << " threads)..." << std::endl;

        std::vector<std::thread> threads;
        std::atomic<int>         counter(0);

        auto threadFunc = [&counter, logsPerThread](int threadId) {
            for (int i = 0; i < logsPerThread; ++i) {
                // 生成不同长度的消息
                std::string msg = "Stress-" + std::to_string(threadId) + "-" + std::to_string(i);
                for (int j = 0; j < (i % 10); ++j) {
                    msg += " padding";
                }
                LOG_INFO << msg << " Counter=" << counter.fetch_add(1);

                // 随机延迟模拟真实负载
                if (i % 100 == 0) {
                    std::this_thread::sleep_for(std::chrono::microseconds(10));
                }
            }
        };

        auto start = high_resolution_clock::now();

        for (int i = 0; i < result.numThreads; ++i) {
            threads.emplace_back(threadFunc, i);
        }

        for (auto& t : threads) {
            t.join();
        }

        auto end      = high_resolution_clock::now();
        auto duration = duration_cast<milliseconds>(end - start);

        result.totalTimeMs  = duration.count();
        result.throughput   = (result.numLogs * 1000.0) / result.totalTimeMs;
        result.avgLatencyUs = (result.totalTimeMs * 1000.0) / result.numLogs;

        std::cout << "  Completed in " << result.totalTimeMs << "ms" << std::endl;

        // 等待异步写入完成
        std::this_thread::sleep_for(std::chrono::seconds(2));

        return result;
    }

    static Result messageLengthBenchmark(int messageLength)
    {
        Result result;
        result.name       = "Message Length " + std::to_string(messageLength);
        result.numThreads = 1;
        result.numLogs    = 10000;

        std::cout << "Running message length benchmark (" << messageLength << " chars)..."
                  << std::endl;

        // 生成指定长度的消息
        std::string longMessage(messageLength, 'X');

        auto start = high_resolution_clock::now();

        for (int i = 0; i < result.numLogs; ++i) {
            LOG_INFO << "Msg-" << i << " " << longMessage;
        }

        auto end      = high_resolution_clock::now();
        auto duration = duration_cast<milliseconds>(end - start);

        result.totalTimeMs  = duration.count();
        result.throughput   = (result.numLogs * 1000.0) / result.totalTimeMs;
        result.avgLatencyUs = (result.totalTimeMs * 1000.0) / result.numLogs;

        std::cout << "  Completed in " << result.totalTimeMs << "ms" << std::endl;

        // 等待异步写入完成
        std::this_thread::sleep_for(std::chrono::seconds(1));

        return result;
    }

    static void printResults(const std::vector<Result>& results)
    {
        std::cout << std::endl;
        std::cout << "=== Benchmark Results ===" << std::endl;
        std::cout << std::endl;

        // 打印表头
        std::cout << std::left << std::setw(25) << "Test Name" << std::setw(10) << "Threads"
                  << std::setw(12) << "Total Logs" << std::setw(12) << "Time (ms)" << std::setw(15)
                  << "Throughput" << std::setw(15) << "Avg Latency" << std::endl;

        std::cout << std::string(90, '-') << std::endl;

        // 打印结果
        for (const auto& r : results) {
            std::cout << std::left << std::setw(25) << r.name << std::setw(10) << r.numThreads
                      << std::setw(12) << r.numLogs << std::setw(12) << std::fixed
                      << std::setprecision(2) << r.totalTimeMs << std::setw(15) << std::fixed
                      << std::setprecision(0) << r.throughput << " logs/s" << std::setw(15)
                      << std::fixed << std::setprecision(2) << r.avgLatencyUs << " us" << std::endl;
        }

        std::cout << std::endl;

        // 计算总体统计
        double totalLogs = 0;
        double totalTime = 0;
        for (const auto& r : results) {
            totalLogs += r.numLogs;
            totalTime += r.totalTimeMs;
        }

        std::cout << "=== Overall Statistics ===" << std::endl;
        std::cout << "Total logs written: " << static_cast<int>(totalLogs) << std::endl;
        std::cout << "Total time: " << totalTime / 1000.0 << " seconds" << std::endl;
        std::cout << "Average throughput: " << std::fixed << std::setprecision(0)
                  << (totalLogs * 1000.0 / totalTime) << " logs/sec" << std::endl;
    }
};

int main()
{
    try {
        Benchmark::runAllBenchmarks();
    }
    catch (const std::exception& e) {
        std::cerr << "Benchmark failed: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}
